namespace hms {

template<typename MeshType>
MeshType uniMeshAs(
	Index  nCellsX,
	Index  nCellsY,
	scalar dx,
	scalar dy,
	bool   addBoundaryPatches,
	scalar offsetX,
	scalar offsetY
){
	return uniMeshAs<MeshType>(
		Array2i{nCellsX, nCellsY},
		Array2s{dx, dy},
		Array2s{offsetX, offsetY},
		addBoundaryPatches
	);
}

/* All overloads below are intended for testing purposes,
 * so that isUniform() and isRectangular() can be called on a mesh directly,
 * with no additional parameters, while still properly chaining the calls to
 * less specific types (isUniform() calls isRectangular() calls isStructured())
 * */

template<typename MeshType>
bool isRectangular(
	const MeshBase<MeshType>& mesh,
	const Ref<const VectorXs>& xCoords,
	const Ref<const VectorXs>& yCoords,
	const std::vector<IdxVector>& edgesAtVertices
){
	if constexpr ( !std::is_base_of_v<StructMeshBase<MeshType>, MeshType> ){
		if ( !isStructured(mesh.derived(), edgesAtVertices) )
			return false;
	}
	return isRectangular(
		mesh.nDomainCells(),
		xCoords,
		yCoords
	);
}

template<typename MeshType>
bool isRectangular( const MeshBase<MeshType>& mesh ){
	auto [xCoords,yCoords] = uniqueCoordinates( mesh.derived().vertices() );
	return isRectangular( mesh, xCoords, yCoords );
}


template<typename MeshType>
bool isUniform(
	const MeshBase<MeshType>& mesh,
	const Ref<const VectorXs>& xCoords,
	const Ref<const VectorXs>& yCoords,
	const std::vector<IdxVector>& edgesAtVertices
){
	if ( !isRectangular( mesh, xCoords, yCoords, edgesAtVertices ) )
		return false;
	return isUniform(
		xCoords,
		yCoords
	);
}


template<typename MeshType>
bool isUniform( const MeshBase<MeshType>& mesh ){
	auto [xCoords,yCoords] = uniqueCoordinates( mesh.derived().vertices() );
	return isUniform( mesh, xCoords, yCoords );
}



}